From acfc6e9b34b3b3ca0d8bbe366dd08b0fac21c740 Mon Sep 17 00:00:00 2001
From: Yunhui Cui <yunhui.cui@nxp.com>
Date: Tue, 2 Feb 2016 12:21:12 +0800
Subject: [PATCH 101/113] mtd: spi-nor: fsl-quadspi: extend support for some
 special requerment.

Add extra info in LUT table to support some special requerments.
Spansion S25FS-S family flash need some special operations.

Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
---
 drivers/mtd/spi-nor/fsl-quadspi.c |   44 +++++++++++++++++++++++++++++++++++--
 include/linux/mtd/spi-nor.h       |    4 ++++
 2 files changed, 46 insertions(+), 2 deletions(-)

--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -205,6 +205,9 @@
 #define SEQID_RDCR		9
 #define SEQID_EN4B		10
 #define SEQID_BRWR		11
+#define SEQID_RDAR		12
+#define SEQID_WRAR		13
+
 
 #define QUADSPI_MIN_IOMAP SZ_4M
 
@@ -470,6 +473,28 @@ static void fsl_qspi_init_lut(struct fsl
 	qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR),
 			base + QUADSPI_LUT(lut_base));
 
+	/*
+	 * Read any device register.
+	 * Used for Spansion S25FS-S family flash only.
+	 */
+	lut_base = SEQID_RDAR * 4;
+	qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_SPANSION_RDAR) |
+			LUT1(ADDR, PAD1, ADDR24BIT),
+			base + QUADSPI_LUT(lut_base));
+	qspi_writel(q, LUT0(DUMMY, PAD1, 8) | LUT1(FSL_READ, PAD1, 1),
+			base + QUADSPI_LUT(lut_base + 1));
+
+	/*
+	 * Write any device register.
+	 * Used for Spansion S25FS-S family flash only.
+	 */
+	lut_base = SEQID_WRAR * 4;
+	qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_SPANSION_WRAR) |
+			LUT1(ADDR, PAD1, ADDR24BIT),
+			base + QUADSPI_LUT(lut_base));
+	qspi_writel(q, LUT0(FSL_WRITE, PAD1, 1),
+			base + QUADSPI_LUT(lut_base + 1));
+
 	fsl_qspi_lock_lut(q);
 }
 
@@ -477,9 +502,15 @@ static void fsl_qspi_init_lut(struct fsl
 static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
 {
 	switch (cmd) {
+	case SPINOR_OP_READ4_1_1_4:
 	case SPINOR_OP_READ_1_1_4:
 	case SPINOR_OP_READ_FAST:
+	case SPINOR_OP_READ4_FAST:
 		return SEQID_READ;
+	case SPINOR_OP_SPANSION_RDAR:
+		return SEQID_RDAR;
+	case SPINOR_OP_SPANSION_WRAR:
+		return SEQID_WRAR;
 	case SPINOR_OP_WREN:
 		return SEQID_WREN;
 	case SPINOR_OP_WRDI:
@@ -491,6 +522,7 @@ static int fsl_qspi_get_seqid(struct fsl
 	case SPINOR_OP_CHIP_ERASE:
 		return SEQID_CHIP_ERASE;
 	case SPINOR_OP_PP:
+	case SPINOR_OP_PP_4B:
 		return SEQID_PP;
 	case SPINOR_OP_RDID:
 		return SEQID_RDID;
@@ -830,8 +862,12 @@ static int fsl_qspi_read_reg(struct spi_
 {
 	int ret;
 	struct fsl_qspi *q = nor->priv;
+	u32 to = 0;
+
+	if (opcode == SPINOR_OP_SPANSION_RDAR)
+		memcpy(&to, nor->cmd_buf, 4);
 
-	ret = fsl_qspi_runcmd(q, opcode, 0, len);
+	ret = fsl_qspi_runcmd(q, opcode, to, len);
 	if (ret)
 		return ret;
 
@@ -843,9 +879,13 @@ static int fsl_qspi_write_reg(struct spi
 {
 	struct fsl_qspi *q = nor->priv;
 	int ret;
+	u32 to = 0;
+
+	if (opcode == SPINOR_OP_SPANSION_WRAR)
+		memcpy(&to, nor->cmd_buf, 4);
 
 	if (!buf) {
-		ret = fsl_qspi_runcmd(q, opcode, 0, 1);
+		ret = fsl_qspi_runcmd(q, opcode, to, 1);
 		if (ret)
 			return ret;
 
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -74,6 +74,10 @@
 /* Used for Spansion flashes only. */
 #define SPINOR_OP_BRWR		0x17	/* Bank register write */
 
+/* Used for Spansion S25FS-S family flash only. */
+#define SPINOR_OP_SPANSION_RDAR	0x65	/* Read any device register */
+#define SPINOR_OP_SPANSION_WRAR	0x71	/* Write any device register */
+
 /* Used for Micron flashes only. */
 #define SPINOR_OP_RD_EVCR      0x65    /* Read EVCR register */
 #define SPINOR_OP_WD_EVCR      0x61    /* Write EVCR register */
